﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;

namespace Cap
{
    internal class CapBuilder : ICapBuilder
    {
        public IServiceCollection Services { get; }

        private bool hasEndpoints = false;

        public CapBuilder(IServiceCollection services)
        {
            Services = services;
        }

        public ICapBuilder AddCapStrategy<TCapStrategy>(Func<IServiceProvider, TCapStrategy> configure)
            where TCapStrategy : class, ICapStrategy
        {
            Services.TryAddTransient(configure);
            Services.TryAddScoped(typeof(IPub<>), typeof(Pub<>));
            return this;
        }

        public ICapBuilder AddEventSource<TEventSource>(string subject, Action<TEventSource> configure)
            where TEventSource : IEventSource, new()
        {
            Services.AddSingleton(sp =>
            {
                var source = new TEventSource();
                configure(source);
                return source.Build(subject);
            });
            return this;
        }

        public ICapBuilder UseEndpoints(Action<IEndpointBuilder> endpoints)
        {
            if (!hasEndpoints)
            {
                var endpointBuilder = new EndpointBuilder();
                endpoints(endpointBuilder);
                var @delegate = endpointBuilder.Build();
                Services.AddHostedService(sp =>
                {
                    return ActivatorUtilities
                        .CreateInstance<EventHostedService>(sp, new BranchOptions(@delegate));
                });
                hasEndpoints = true;
            }
            return this;
        }
    }
}
